Dart _fe_analyzer_shared scanner AbstractScanner tokenize
tokenize
主要任务是将输入的源代码转换为一个词素流,AbstractScanner 类最核心方法。
调用处
全局搜索调用 tokenize()
的地方,就能知道全局在哪里启动了编译的初步流程。
pkg\analysis_server\lib\src\lsp\source_edits.dart
pkg\analysis_server\lib\src\services\correction\statement_analyzer.dart
pkg\analysis_server\lib\src\services\correction\util.dart
pkg\analyzer\lib\dart\analysis\utilities.dart
pkg\analyzer\lib\src\fasta\doc_comment_builder.dart
pkg\front_end\lib\src\fasta\util\parser_ast.dart
- fasta 的 genAST 方法中调用
- 此处值得注意
pkg\front_end\lib\src\fasta\util\textual_outline.dart
pkg\front_end\tool\dart_doctest_impl.dart
pkg\front_end\tool\duplicate_code_finder_experiment.dart
pkg\front_end\tool\_fasta\parser_ast_helper_creator.dart
pkg\scrape\lib\scrape.dart
以上代码中,省略了各个 test 目录下的代码。
代码实现
@override
Token tokenize() {
// 首先,它进入一个循环
// 只要没有到达文件的末尾,就会继续执行循环。
while (!atEndOfFile()) {
// 在每次循环中,它首先调用
// `advance` 方法来获取下一个字符。
int next = advance();
// 然后,它会检查是否已经读取到文件的末尾。
// Scan the header looking for a language version
if (!identical(next, $EOF)) {
// 如果没有
Token oldTail = tail;
// 它会调用 `bigHeaderSwitch` 方法
// 来处理文件头部的语言版本信息。
next = bigHeaderSwitch(next);
// 如果读取到的字符是脚本词素
if (!identical(next, $EOF) && tail.kind == SCRIPT_TOKEN) {
// 它会再次调用 `bigHeaderSwitch` 方法。
oldTail = tail;
next = bigHeaderSwitch(next);
}
// 然后,只要没有读取到文件的末尾,并且最后一个词素没有改变,
// 它会继续调用 `bigHeaderSwitch` 方法。
while (!identical(next, $EOF) && tail == oldTail) {
next = bigHeaderSwitch(next);
}
next = next;
}
// 接下来,只要没有读取到文件的末尾
// 它会调用 `bigSwitch` 方法来处理剩余的字符。
while (!identical(next, $EOF)) {
next = bigSwitch(next);
}
// 如果已经读取到文件的末尾
// 它会调用 `appendEofToken` 方法
// 来添加一个表示文件结束的词素。
if (atEndOfFile()) {
appendEofToken();
} else {
// 否则,它会调用 `unexpectedEof` 方法
// 来处理意外的文件结束。
unexpectedEof();
}
}
// 在循环结束后,它会将字符串偏移量加一并添加到行开始的列表中,
// 这是为了模拟文件末尾的行。
// Always pretend that there's a line at the end of the file.
lineStarts.add(stringOffset + 1);
// 最后,它会调用 `firstToken` 方法来返回词素流的第一个词素。
return firstToken();
}
类属性
-
tokenStart
:- 表示下一个将被创建的词素的字符串偏移量。
- 在
Utf8BytesScanner
中,stringOffset
和scanOffset
的值是不同的,因为一个字符串字符可以使用多个 UTF-8 字节进行编码。 - 初始值为
-1
,表示还没有开始扫描 int
类型
-
tokens
:- 表示由这个扫描器创建的词素流。
- 第一个词素是一个特殊的词素,它不是源文件的一部分,这是为了避免在扫描器中的特殊情况。
- 这个词素不会暴露给扫描器的客户端,客户端应该调用
firstToken
方法来访问词素流。 Token
类型
-
tail
:- 表示最后扫描的词素。
- 这个属性是使用
late
关键字声明的,表示它将在稍后进行初始化。 Token
类型
本文作者:Maeiee
本文链接:Dart _fe_analyzer_shared scanner AbstractScanner tokenize
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!